#ifndef CHAPTER15_PRACTICE3_EXC_MEAN_H_
#define CHAPTER15_PRACTICE3_EXC_MEAN_H_

#include <iostream>
#include <stdexcept>
#include <string>
#include <cmath>
using namespace std;

class bad_hmean3 :public logic_error
{
private:
	string name;
public:
	double v1;
	double v2;
	explicit bad_hmean3(double a = 0, double b = 0, const string &s = "Error in hmean()\n");
	void mesg();
	virtual ~bad_hmean3() throw() { }
};

bad_hmean3::bad_hmean3(double a, double b, const string & s) :
	v1(a), v2(b), logic_error(s)
{
	name = "hmean";
}

inline void bad_hmean3::mesg()
{
	cout << name << "(" << v1 << "," << v2 << ")arguments a=-b should be div a+b!=0\n";
}

class bad_gmean3:public bad_hmean3
{
private:
	string name;
public:
	explicit bad_gmean3(double a = 0, double b = 0, const string &s = "Error in gmean()\n");
	void mesg();
	virtual ~bad_gmean3() throw() { }
};

bad_gmean3::bad_gmean3(double a, double b, const string &s) :bad_hmean3(a, b, s)
{
	name = "gmean";
}

inline void bad_gmean3::mesg()
{
	cout << name << "(" << bad_hmean3::v1 << ", " << bad_hmean3::v2 << ")arguments should be >=0\n";
}

double practice15_hmean(double a, double b)
{
	if (a == -b)
		throw bad_hmean3(a,b);
	return 2.0*a*b / (a + b);
}

double practice15_gmean(double a, double b)
{
	if (a < 0 || b < 0)
		throw bad_gmean3(a,b);
	return sqrt(a*b);
}

#endif // !CHAPTER15_PRACTICE3_EXC_MEAN_H_
